<?php

if (!defined('IN_XLP')) {
    exit('Access Denied!');
}

/**
 * Description of weixinJsApi
 * 微信JSAPI接口处理类
 * @author xlp
 */
class weixinJsApi {

    const API_URL_PREFIX = 'https://api.weixin.qq.com/cgi-bin';
    const TICKET_URL = '/ticket/getticket?type=jsapi&';
    const AUTH_URL = '/token?grant_type=client_credential&';

    private $appid;
    private $appsecret;
    private $accessToken;
    public $errCode = 40001;
    public $errMsg = 'no access';
    private $accessTokenPre = 'token/weixin/access_token_';
    private $ticketPre = 'token/weixin/jsticket_';

    public function __construct($options = array()) {
        $this->appid = isset($options['appid']) ? $options['appid'] : '';
        $this->appsecret = isset($options['appsecret']) ? $options['appsecret'] : '';
        if (!$this->appid || !$this->appsecret) {
            $userInfo = F('weixin/setting');
            if (isHave($userInfo['user_info']['wx_AppId']) && isHave($userInfo['user_info']['wx_AppSecret'])) {
                $this->appid = $userInfo['user_info']['wx_AppId'];
                $this->appsecret = $userInfo['user_info']['wx_AppSecret'];
            } else {
                showError('api Error:请设置appid和appsecret');
            }
        }
    }

    /*
     * jsAPI接口，获取签名参数
     */

    public function getSignPackage() {
        $jsapiTicket = $this->getJsApiTicket();
        $nonceStr = getRandInt();
        // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=" . TIME . "&url=" . URL;
        
        $signPackage = array(
            'appId' => $this->appid,
            'nonceStr' => $nonceStr,
            'timestamp' => TIME,
            'url' => URL,
            'signature' => sha1($string),
            'rawString' => $string
        );
        return $signPackage;
    }

    /**
     * 删除验证数据
     * @param string $appid
     */
    public function resetAuth() {
        $this->accessToken = '';
        S($this->accessTokenPre . $this->appid, null);
        $this->checkAuth();
        return true;
    }

    /*
     * 检查是否需要重新获取accesstoken
     * 并记下日志
     */

    public function checkAccessToken() {
        if ($this->errCode == 40001) {
            $this->resetAuth();
            saveLog('accessToken/reset', 'weixin.api');
            return true;
        }
        return false;
    }

    private function getJsApiTicket() {
        $this->jsTicket = S($this->ticketPre . $this->appid);
        if ($this->jsTicket) {
            return $this->jsTicket;
        }
        if (!$this->accessToken && !$this->checkAuth()) {
            return false;
        }
        $result = getHttp(self::API_URL_PREFIX . self::TICKET_URL . 'access_token=' . $this->accessToken);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json || !empty($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                if ($this->checkAccessToken()) {
                    return $this->getJsApiTicket();
                }
                return false;
            }
            $this->jsTicket = $json['ticket'];
            S($this->ticketPre . $this->appid, $json['ticket'], $json['expires_in'] - 100);
        }
        return $this->ticketPre;
    }

    /**
     * 通用auth验证方法，暂时仅用于菜单更新操作
     * @param string $appid
     * @param string $appsecret
     */
    private function checkAuth() {
        if (!$this->appid || !$this->appsecret) {
            saveLog('accessToken/lose', 'weixin.api');
            return false;
        }
        if ($this->accessToken) {
            return $this->accessToken;
        }
        $this->accessToken = S($this->accessTokenPre . $this->appid);
        if ($this->accessToken) {
            return $this->accessToken;
        }
        $result = getHttp(self::API_URL_PREFIX . self::AUTH_URL . 'appid=' . $this->appid . '&secret=' . $this->appsecret);
        if ($result) {
            $json = json_decode($result, true);
            if (!$json || isset($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            $this->accessToken = $json['access_token'];
            S($this->accessTokenPre . $this->appid, $json['access_token'], $json['expires_in'] - 100);
        }
        return $this->accessToken;
    }

}
